import re
import pandas as pd
from operator import methodcaller
import os


def get_file_df(note_dir):
    file_name_list, file_path_list = [], []
    for root, folder, file in os.walk(note_dir):
        if root.endswith("assets") or "logseq" in root:
            continue
        file_name_list.extend(file)
        for f in file:
            file_path_list.append(os.path.join(root, f))

    file_df = pd.DataFrame({"path": file_path_list, "name": file_name_list})
    file_df["dir"] = file_df["path"].apply(os.path.dirname)
    func_endswith_md = methodcaller("endswith", ".md")
    file_df = file_df[file_df["name"].apply(func_endswith_md)]
    get_page_property(file_df)
    # def apply_relink_changed_file(row, type_name, change_property_list):
    return file_df


def change_date(file_df):
    for file in file_df["path"].tolist():
        with open(file, encoding="utf8") as f:
            note = f.read()
        date_list = re.findall("\[\[ *\d{1,2}-\d{1,2}-\d{4}\]\]", note)
        if len(date_list) > 0:
            date_digit_list = [re.findall("(\d{1,2})-(\d{1,2})-(\d{4})", item)[0] for item in date_list]
            for date, date_digit in zip(date_list, date_digit_list):
                note = note.replace(date, f"[[{int(date_digit[2]):4d}-{int(date_digit[0]):02d}-{int(date_digit[1]):02d}]]")
            with open(file, "w", encoding="utf8") as f:
                f.write(note)


def get_page_property(file_df):
    for file in file_df["path"].tolist():
        with open(file, encoding="utf8") as f:
            note = f.read()
        if "::" not in note:
            continue
        if "\n\n" in note:
            property, body = note.split("\n\n", 1)
        else:
            property = note
        if "::" not in property:
            continue
        property_dict = {}
        for line in property.split("\n"):
            line_property = line.strip().split("::")
            if len(line_property) == 2 and line_property[-1] != "":
                p, v = line_property
                property_dict[p] = [item.strip() for item in v.split(",")]
            elif line_property[0] == "":
                continue
            else:
                property_dict[line_property[0]] = None
        file_df.loc[file_df["path"] == file, "page_property"] = [property_dict]


def get_property_dict(file_df, property_list):
    page_property = file_df.loc[~file_df["page_property"].isna(), "page_property"].tolist()
    property_keys = set([i for item in page_property for i in item.keys()])
    property_dict = {p: [] for p in property_keys}
    property_sub_dict = {item: {} for item in property_list}

    def apply_get_property_page_dict(row, property_dict):
        for p in row["page_property"]:
            if row["page_property"][p] is not None:
                property_dict[p].append(row["name"])

    def apply_get_property_sub_page_dict(row, property_list):
        for property in property_list:
            if property in row["page_property"] and row["page_property"][property] is not None:
                property_value_list = row["page_property"][property]
                for p in property_value_list:
                    if p not in property_sub_dict:
                        property_sub_dict[property][p] = [row["name"]]
                    else:
                        property_sub_dict[property][p].append(row["name"])

    _ = file_df.loc[~file_df["page_property"].isna()].apply(apply_get_property_page_dict, axis=1, args=(property_dict,))
    _ = file_df.loc[~file_df["page_property"].isna()].apply(apply_get_property_sub_page_dict, axis=1, args=(property_list,))
    return property_dict, property_sub_dict


def rename_by_type(file_df, type_name):
    def apply_rename_by_type(row, type_name):
        if (
            "type" in row["page_property"]
            and row["page_property"]["type"] is not None
            and type_name in row["page_property"]["type"]
            and not row["name"].startswith(type_name.strip("#") + "-")
        ):
            os.rename(row["path"], os.path.join(row["dir"], type_name.strip("#") + "-" + row["name"]))
            return True

    file_df[~file_df["page_property"].isna()].apply(apply_rename_by_type, axis=1, args=(type_name,))


def rename_property(file_df, ori_name, new_name):
    def apply_rename_property(row, ori_name, new_name):
        if ori_name in row["page_property"]:
            with open(row["path"], encoding="utf8") as f:
                note = f.read()
            if new_name + "::" not in note:
                note = note.replace(ori_name + "::", new_name + "::")
            with open(row["path"], "w", encoding="utf8") as f:
                f.write(note)

    file_df[~file_df["page_property"].isna()].apply(
        apply_rename_property,
        axis=1,
        args=(ori_name, new_name),
    )


def relink_changed_property(file_df, type_name, change_property_list):
    def apply_relink_changed_file(row, type_name, change_property_list):
        if "type" in row["page_property"] and row["page_property"]["type"] is not None and type_name in row["page_property"]["type"]:
            print(row["name"])
            with open(row["path"], encoding="utf8") as f:
                note = f.read()
            for change_property in change_property_list:
                if change_property not in row["page_property"] or row["page_property"][change_property] is None:
                    continue
                for item in row["page_property"][change_property]:
                    if "#" not in item and not item.startswith("[[" + change_property):
                        note = note.replace(item, "[[" + change_property + "-" + item[2:])
            with open(row["path"], "w", encoding="utf8") as f:
                f.write(note)

    file_df[~file_df["page_property"].isna()].apply(
        apply_relink_changed_file,
        axis=1,
        args=(
            type_name,
            change_property_list,
        ),
    )


if __name__ == "__main__":
    note_dir = "C:\\Users\\isidore\\OneDrive\\documents\\noteasy\\pages"
    # file_df = get_file_df(note_dir)
    # rename_property(file_df, "laboratory", "ac-laboratory")
    # rename_by_type(file_df, "#paper")
    # rename_by_type(file_df, "#ac-task")
    # rename_by_type(file_df, "#ac-publisher")
    # rename_by_type(file_df, "#ac-laboratory")
    # rename_by_type(file_df, "#ac-project")
    # file_df = get_file_df(note_dir)
    # relink_changed_property(file_df, "#paper", ["ac-task", "ac-publisher", "ac-laboratory", "ac-project"])
